package com.oss.quartz;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.oss.util.JsonMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.OSSObject;
import com.oss.base.BaseConst;
import com.oss.base.baseconst.ConfigConst;
import com.oss.base.dao.DaoUtil;
import com.oss.base.dao.IBaseDao;
import com.oss.vo.FlowLimit;
import com.oss.vo.OssStatistics;
import com.oss.vo.SysUser;
@Component
public class FlowCalcQuartz {
	Logger logger = Logger.getLogger(this.getClass());
	@Autowired
	IBaseDao baseDao;
	
	@Scheduled(cron="0 19 */1 * * *")
	public void saveFlowCalc(){
		// /LOG/testofwjt2016-02-03-08-00-00-0001
//		// /LOG/testofwjt2016-01-21-14-00-00-0001
		logger.info("begin");
//		File file=new File("E:/工作/项目/云存储OSS/test/20160121/1");
		
		OSSClient client = new OSSClient(ConfigConst.ENDPOINT, ConfigConst.ACCESSKEYID, ConfigConst.ACCESSKEYSECRET);
		SimpleDateFormat dft=new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");     
		Date date = new Date();      
		Calendar   dar=Calendar.getInstance();     
		dar.setTime(date);     
		dar.add(java.util.Calendar.HOUR_OF_DAY, -3);
		dar.set(Calendar.SECOND,0);
		dar.set(Calendar.MINUTE,0);
		String dateStr = dft.format(dar.getTime());
		String key = "LOG/testofwjt"+dateStr+"-0001";
//		key =  "LOG/testofwjt2016-01-22-10-00-00-0001";
		int i = 0;
		OSSObject object = client.getObject(new GetObjectRequest(ConfigConst.BUCKETNAME, key));
		InputStreamReader read=null;
		BufferedReader bufferedReader=null;
		try {
			HashMap<String, OssStatistics> map = new HashMap<String, OssStatistics>();
			read = new InputStreamReader(object.getObjectContent(),"utf-8");
			
//			read = new InputStreamReader(new FileInputStream(file),"utf-8");
			bufferedReader = new BufferedReader(read);
			String tmp;
			while((tmp = bufferedReader.readLine()) != null){
				i++;
				try {
					OssStatistics ossStat = buildStatistics(tmp.split("\" \""),key);
					
					if(map.containsKey(ossStat.genKey())){
						map.put(ossStat.genKey(), updateStat(map.get(ossStat.genKey()),ossStat));
					}else{
						map.put(ossStat.genKey(),ossStat);
					}
				} catch (Exception e) {
					e.printStackTrace();
					logger.info(tmp);
				}
				
			}
//			baseDao.save(buildLimits(map.values(),new SimpleDateFormat("yyyy-MM").format(dar.getTime())).get(0));
			baseDao.saveOrUpdateAll(buildLimits(map.values(),new SimpleDateFormat("yyyy-MM").format(dar.getTime())));
			logger.info("deal row:"+i+" ,insert row:"+map.values().size());
//			OssStatistics o = map.values().iterator().next();
//			System.out.println(DaoUtil.getSqlInset(o));
//			System.out.println(JsonMapper.buildNonDefaultMapper().toJson(o));
//			baseDao.save(o);
			baseDao.saveOrUpdateAll(map.values());
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			try {
				bufferedReader.close();
				read.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		logger.info("end");
	
	}

	private List<FlowLimit> buildLimits(Collection<OssStatistics> values, String time) {
		
		DetachedCriteria dc = DetachedCriteria.forClass(FlowLimit.class);
	    dc.add(Restrictions.eq("time", time)); 
		
		List<FlowLimit> limits = baseDao.findByCriteria(dc);
		
		if(limits != null && limits.size() >0){
			for(FlowLimit limit:limits){
				
				for(OssStatistics stat:values){
					if(stat.getOssKey().equals(limit.getOssKey())){
						updateLimit(limit,stat);
					}
				}
				
			}
		}else{
			Map<String,FlowLimit> map = new HashMap<String,FlowLimit>();
			
			for(OssStatistics stat:values){
				if(map.containsKey(stat.getOssKey())){
					updateLimit(map.get(stat.getOssKey()),stat);
				}else{
					map.put(stat.getOssKey(), buildLimit(stat,time));
				}
			}
			limits.addAll(map.values()); 
		}
		
		return limits;
	}

	private FlowLimit buildLimit(OssStatistics stat, String time) {
		FlowLimit limit = new FlowLimit();
		limit.setDownFlowLimit(limit.getDownFlowLimit()+stat.getTotalDownFlow());
		limit.setUpFlowLimit(limit.getUpFlowLimit()+stat.getTotalUpFlow());
		limit.setVisitLimit(limit.getVisitLimit()+stat.getTotalVisits());
		limit.setTime(time);
		limit.setOssKey(stat.getOssKey());
		return limit;
	}

	private void updateLimit(FlowLimit limit, OssStatistics stat) {
		limit.setDownFlowLimit(limit.getDownFlowLimit()+stat.getTotalDownFlow());
		limit.setUpFlowLimit(limit.getUpFlowLimit()+stat.getTotalUpFlow());
		limit.setVisitLimit(limit.getVisitLimit()+stat.getTotalVisits());
		
		
		
	}

	private OssStatistics updateStat(OssStatistics oss,
			OssStatistics ossStat) {
		oss.setSucVisits(oss.getSucVisits()+ossStat.getSucVisits());
		oss.setFaledVisits(oss.getFaledVisits()+ossStat.getFaledVisits());
		oss.setTotalDownFlow(oss.getTotalDownFlow()+ossStat.getTotalDownFlow());
		oss.setTotalUpFlow(oss.getTotalUpFlow()+ossStat.getTotalUpFlow());
		oss.setTotalOssCost(oss.getTotalOssCost()+ossStat.getTotalOssCost());
		oss.setTotalReqCost(oss.getTotalReqCost()+ossStat.getTotalReqCost());
		oss.setTotalVisits(oss.getTotalVisits()+ossStat.getTotalVisits());
		
		oss.setAvgUpFlow(oss.getTotalUpFlow()/oss.getTotalVisits());
		oss.setAvgDownFlow(oss.getTotalDownFlow()/oss.getTotalVisits());
		oss.setAvgOssCost(oss.getTotalOssCost()/oss.getTotalVisits());
		oss.setAvgReqCost(oss.getTotalReqCost()/oss.getTotalVisits());
		return oss;
	}

	private OssStatistics buildStatistics(String[] tmps, String key) {
		OssStatistics oss = new OssStatistics();
		String[] infos = tmps[0].split(" ");
		String[] objInfos = tmps[8].split(" ");
		
		if(BaseConst.HTTP_STATUS_SUCCESS.equalsIgnoreCase(infos[9])){
			oss.setSucVisits(1);
			oss.setFaledVisits(0);
		}else{
			oss.setSucVisits(0);
			oss.setFaledVisits(1);
		}
		
		if(infos[6].endsWith(BaseConst.HTTP_REQUEST_GET)){
			long flow = parse(infos[10]);
			oss.setAvgDownFlow(flow);
			oss.setTotalDownFlow(flow);
			oss.setAvgUpFlow(0);
			oss.setTotalUpFlow(0);
		}else{
			long size = parse(objInfos[1]);
			long upflow = size == 0?parse(objInfos[6]):size;
			oss.setAvgDownFlow(0);
			oss.setTotalDownFlow(0);
			oss.setAvgUpFlow(upflow);
			oss.setTotalUpFlow(upflow);
		}
		long ossCost = parse(objInfos[3]);
		long reqCost = parse(infos[11]);
		oss.setAvgOssCost(ossCost);
		oss.setAvgReqCost(reqCost);
		oss.setTotalOssCost(ossCost);
		oss.setTotalReqCost(reqCost);
		oss.setFileName(key);
		oss.setMethod(tmps[6]);
		oss.setOwnerId(objInfos[5]);
		oss.setOssKey(objInfos[0].split("%2F")[0]);
		oss.setBucket(tmps[7]);
		oss.setEndpoint(tmps[2]);
		oss.setReqId(tmps[5]);
		oss.setTotalVisits(1);
		
		return oss;
	}
	
	public long parse(String s){
		try {
			return Long.parseLong(s);
		} catch (Exception e) {
			return 0;
		}
		
	}
	
	
	
}
